//build: gcc -g xi2.c -o /tmp/xi2 -lX11 -lXi 

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <string.h>
#include <stdlib.h>


int main(void) {
    Display*    dpy     = XOpenDisplay(0);
    Window root_window = DefaultRootWindow(dpy);
    XIEventMask xim;
    //注意特定设备(deviceid)和特定掩码(mask)匹配, 否则XISelectEvents报错
    xim.deviceid = XIAllDevices;
    xim.mask_len = XIMaskLen(XI_LASTEVENT);
    xim.mask = malloc(xim.mask_len);
    memset(xim.mask, 0, xim.mask_len);
    printf("xi mask len:%d\n", xim.mask_len);
    XISetMask(xim.mask, XI_ButtonPress);
    //XISetMask(xim.mask, XI_TouchBegin); //error touch for special device
    XISelectEvents(dpy, root_window,  &xim, 1);
    free(xim.mask);
    
    /* get a list of all input devices */
    int num_devices, i;
    XIDeviceInfo *devices = XIQueryDevice(dpy, XIAllDevices, &num_devices);
    /* loop through all devices looking for touch events */
    for (i = 0; i < num_devices; i++) {
        XIDeviceInfo *device = &devices[i];
        if (device->use == XISlavePointer) {
            XIEventMask event_mask;
            event_mask.deviceid = device->deviceid;
            event_mask.mask_len = XIMaskLen(XI_TouchEnd);
            event_mask.mask = malloc(event_mask.mask_len);
            memset(event_mask.mask, 0, event_mask.mask_len);
            XISetMask(event_mask.mask, XI_TouchBegin);
            XISetMask(event_mask.mask, XI_TouchUpdate);
            XISetMask(event_mask.mask, XI_TouchEnd);
            XISelectEvents(dpy, root_window, &event_mask, 1);
            free(event_mask.mask);
        }
    }
    XEvent      ev;
    XIEvent *xie = NULL;
    while(1) {
        XNextEvent(dpy, &ev);
        if(ev.type != GenericEvent) continue;
        if(XGetEventData(dpy, &ev.xcookie)) {
            xie = (XIEvent *)ev.xcookie.data;
            if(xie != NULL) {
                switch(xie->evtype) {
                case XI_ButtonPress:
                    printf("Recv ButtonPress\n");
                    break;
                case XI_TouchBegin:
                    printf("Recv TouchBegin\n");
                    break;
                case XI_TouchUpdate:
                    printf("Recv TouchUpdate\n");
                    break;
                case XI_TouchEnd:
                    printf("Recv TouchEnd\n");
                    break;
                default:
                    break;
                } 
            }
        }
        XFreeEventData(dpy, &ev.xcookie);
    }
    XCloseDisplay(dpy);
    return 0;
}
